package com.question.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.question.constant.MessageConstant;
import com.question.exception.BaseException;
import com.question.exception.QuestionNotFoundException;
import com.question.mapper.QuestionMapper;
import com.question.mapper.QuestionStatisticsMapper;
import com.question.pojo.dto.QuestionDTO;
import com.question.pojo.entity.*;
import com.question.pojo.result.PageResult;
import com.question.pojo.vo.QuestionVO;
import com.question.service.QuestionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class QuestionServiceImpl implements QuestionService {

    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private QuestionStatisticsMapper questionStatisticsMapper;

//    /**
//     * 获取题目列表
//     *
//     * @param pageNum
//     * @param pageSize
//     * @param questionType
//     * @param keyword
//     * @param categoryId
//     * @param majorId
//     * @return
//     */
//    @Override
//    public PageInfo<QuestionVO> listQuestions(int pageNum, int pageSize, String questionType,
//                                              String keyword, Integer categoryId, Integer majorId) {
//        // 关键修改：使用PageHelper.startPage后必须紧跟查询语句
//        PageHelper.startPage(pageNum, pageSize);
//
//        Map<String, Object> params = new HashMap<>();
//        params.put("questionType", questionType);
//        params.put("keyword", keyword);
//        params.put("categoryId", categoryId);
//        params.put("majorId", majorId);
//
//        // 注意：这里不能有其他数据库操作
//        List<QuestionVO> list = questionMapper.selectQuestionList(params);
//
//        // 使用PageInfo自动获取分页信息
//        return new PageInfo<>(list);
//    }

    /**
     * 获取题目列表
     * @param questionType
     * @param keyword
     * @param majorId
     * @param categoryId
     * @param pageNum
     * @param pageSize
     * @return
     */
    public PageResult getQuestionPage(String questionType, String keyword,
                                      Integer majorId, Integer categoryId,
                                      Integer pageNum, Integer pageSize) {
        // 参数校验
        pageNum = pageNum == null || pageNum < 1 ? 1 : pageNum;
        pageSize = pageSize == null || pageSize < 1 ? 10 : pageSize;

        int offset = (pageNum - 1) * pageSize;
        List<QuestionVO> list = questionMapper.selectQuestionList(
                questionType, keyword, majorId, categoryId, offset, pageSize);
        int total = questionMapper.countQuestionList(
                questionType, keyword, majorId, categoryId);

        return new PageResult(total, list);
    }

    /**
     * 根据 ID 获取题目
     *
     * @param questionId
     * @return
     */
    @Override
    public QuestionVO getQuestionById(Integer questionId) {
        QuestionVO question = questionMapper.getQuestionById(questionId);
        if (question == null) {
            throw new QuestionNotFoundException(MessageConstant.QUESTION_NOT_FOUND);
        }

        QuestionVO vo = new QuestionVO();
        BeanUtils.copyProperties(question, vo);

        // 根据题目类型设置关联数据
        if ("choice".equals(question.getQuestionType())) {
            vo.setChoices(question.getChoices());
        } else if ("fill_in".equals(question.getQuestionType())) {
            vo.setBlanks(question.getBlanks());
        }

        return vo;
    }

    /**
     * 添加题目
     *
     * @param questionDTO
     * @return
     */
    @Override
    @Transactional
    public QuestionVO addQuestion(QuestionDTO questionDTO) {
        // 1. 插入题目主记录
        Question question = new Question();
        BeanUtils.copyProperties(questionDTO, question);

//        question.setMajorId(1);

        // +++ 新增：设置答案字段 +++
        setAnswerField(question, questionDTO);

        questionMapper.insertQuestion(question);

        // 2. 处理关联数据
        if ("choice".equals(question.getQuestionType())) {
            // 设置题目ID并插入选项
            for (Choice choice : questionDTO.getChoices()) {
                choice.setQuestionId(question.getQuestionId());
            }
            questionMapper.insertChoicesBatch(questionDTO.getChoices());
        }
        else if ("fill_in".equals(question.getQuestionType())) {
            // 设置题目ID和空位索引并插入空位
            List<Blank> blanks = new ArrayList<>();
            for (int i = 0; i < questionDTO.getBlanks().size(); i++) {
                Blank blank = questionDTO.getBlanks().get(i);
                blank.setQuestionId(question.getQuestionId());
                blank.setBlankIndex(i + 1);
                blanks.add(blank);
            }
            questionMapper.insertBlanksBatch(blanks);
        }

        QuestionStatistics questionStatistics = new QuestionStatistics();
        questionStatistics.setQuestionId(question.getQuestionId());
        questionStatistics.setTotalAttempts(0);
        questionStatistics.setCorrectAttempts(0);
        questionStatisticsMapper.insert(questionStatistics);

        return getQuestionById(question.getQuestionId());
    }

    /**
     * 删除题目
     *
     * @param questionId
     */
    @Override
    @Transactional
    public void deleteQuestion(Integer questionId) {
        QuestionVO question = questionMapper.getQuestionById(questionId);
        if (question == null) {
            throw new QuestionNotFoundException(MessageConstant.QUESTION_NOT_FOUND);
        }

        // 先删除关联数据
        if ("choice".equals(question.getQuestionType())) {
            questionMapper.deleteChoicesByQuestionId(questionId);
        } else if ("fill_in".equals(question.getQuestionType())) {
            questionMapper.deleteBlanksByQuestionId(questionId);
        }

        // 再删除题目
        questionMapper.deleteQuestion(questionId);
    }

    /**
     * 修改题目
     *
     * @param questionId
     * @param questionDTO
     * @return
     */
    @Override
    @Transactional
    public QuestionVO updateQuestion(Integer questionId, QuestionDTO questionDTO) {
        Question existingQuestion = questionMapper.selectByQuestionId(questionId);
        if (existingQuestion == null) {
            throw new QuestionNotFoundException(MessageConstant.QUESTION_NOT_FOUND);
        }

        // 更新基础信息
        BeanUtils.copyProperties(questionDTO, existingQuestion);

        // 设置答案字段
        setAnswerField(existingQuestion, questionDTO);

        // 执行数据库更新
        questionMapper.updateQuestion(existingQuestion);

        // 记录原题目类型
        String originalType = existingQuestion.getQuestionType();
        String newType = questionDTO.getQuestionType();

        // 类型变更处理
        boolean typeChanged = !originalType.equals(newType);
        if (typeChanged) {
            // 删除旧类型数据
            if ("choice".equals(originalType)) {
                questionMapper.deleteChoicesByQuestionId(questionId);
            } else if ("fill_in".equals(originalType)) {
                questionMapper.deleteBlanksByQuestionId(questionId);
            }

            // 添加新类型数据
            if ("choice".equals(newType)) {
                questionMapper.insertChoicesBatch(questionDTO.getChoices().stream()
                        .map(c -> {
                            c.setQuestionId(questionId);
                            return c;
                        }).collect(Collectors.toList()));
            } else if ("fill_in".equals(newType)) {
                List<Blank> blanks = new ArrayList<>();
                for (int i = 0; i < questionDTO.getBlanks().size(); i++) {
                    Blank blank = questionDTO.getBlanks().get(i);
                    blank.setQuestionId(questionId);
                    blank.setBlankIndex(i + 1);
                    blanks.add(blank);
                }
                questionMapper.insertBlanksBatch(blanks);
            }
        } else {
            // 类型未变更时使用增量更新
            if ("choice".equals(newType)) {
                processChoiceUpdates(questionId, questionDTO);
            } else if ("fill_in".equals(newType)) {
                processBlankUpdates(questionId, questionDTO);
            }
        }

        return getQuestionById(questionId);
    }


    /**
     * 处理选项更新
     *
     * @param questionId
     * @param dto
     */
    private void processChoiceUpdates(Integer questionId, QuestionDTO dto) {
        // 获取数据库中现有的选项
        List<Choice> existingChoices = questionMapper.selectChoicesByQuestionId(questionId);
        Map<Integer, Choice> existingMap = existingChoices.stream()
                .collect(Collectors.toMap(Choice::getChoiceId, Function.identity()));

        // 创建需要更新、插入和保留的选项列表
        List<Choice> toUpdate = new ArrayList<>();
        List<Choice> toInsert = new ArrayList<>();
        Set<Integer> toKeep = new HashSet<>();

        for (Choice newChoice : dto.getChoices()) {
            newChoice.setQuestionId(questionId);

            // 如果选项有ID且在数据库中存在
            if (newChoice.getChoiceId() != null && existingMap.containsKey(newChoice.getChoiceId())) {
                // 检查内容是否变化
                Choice existing = existingMap.get(newChoice.getChoiceId());
                if (!Objects.equals(newChoice.getChoiceContent(), existing.getChoiceContent()) ||
                        !Objects.equals(newChoice.getIsCorrect(), existing.getIsCorrect())) {
                    toUpdate.add(newChoice);
                }
                toKeep.add(newChoice.getChoiceId());
            } else {
                // 新选项
                toInsert.add(newChoice);
            }
        }

        // 批量更新有变化的选项
        if (!toUpdate.isEmpty()) {
            questionMapper.updateChoicesBatch(toUpdate);
        }

        // 批量插入新选项
        if (!toInsert.isEmpty()) {
            questionMapper.insertChoicesBatch(toInsert);
        }

        // 删除不再需要的选项
        List<Integer> toDelete = existingChoices.stream()
                .map(Choice::getChoiceId)
                .filter(id -> !toKeep.contains(id))
                .collect(Collectors.toList());

        if (!toDelete.isEmpty()) {
            questionMapper.deleteChoicesByIds(toDelete);
        }
    }


    /**
     * 处理填空更新
     *
     * @param questionId
     * @param dto
     */
    private void processBlankUpdates(Integer questionId, QuestionDTO dto) {
        // 获取数据库中现有的空位
        List<Blank> existingBlanks = questionMapper.selectBlanksByQuestionId(questionId);

        // 创建索引到空位的映射
        Map<Integer, Blank> existingIndexMap = existingBlanks.stream()
                .collect(Collectors.toMap(Blank::getBlankIndex, Function.identity()));

        // 创建ID到空位的映射
        Map<Integer, Blank> existingIdMap = existingBlanks.stream()
                .collect(Collectors.toMap(Blank::getBlankId, Function.identity()));

        // 验证新空位索引
        Set<Integer> usedIndexes = new HashSet<>();
        for (Blank blank : dto.getBlanks()) {
            if (blank.getBlankIndex() == null) {
                throw new BaseException("空位索引不能为空");
            }
            if (!usedIndexes.add(blank.getBlankIndex())) {
                throw new BaseException("空位索引重复: " + blank.getBlankIndex());
            }
        }

        List<Blank> toUpdate = new ArrayList<>();
        List<Blank> toInsert = new ArrayList<>();

        for (Blank newBlank : dto.getBlanks()) {
            newBlank.setQuestionId(questionId);

            // 检查是否通过索引匹配现有空位
            Blank existingByIndex = existingIndexMap.get(newBlank.getBlankIndex());

            if (existingByIndex != null) {
                // 通过索引找到现有空位 - 更新它
                newBlank.setBlankId(existingByIndex.getBlankId());
                toUpdate.add(newBlank);
            } else if (newBlank.getBlankId() != null && existingIdMap.containsKey(newBlank.getBlankId())) {
                // 通过ID找到现有空位 - 更新它
                toUpdate.add(newBlank);
            } else {
                // 新空位
                toInsert.add(newBlank);
            }
        }

        // 批量更新
        if (!toUpdate.isEmpty()) {
            questionMapper.updateBlanksBatch(toUpdate);
        }

        // 批量插入
        if (!toInsert.isEmpty()) {
            questionMapper.insertBlanksBatch(toInsert);
        }

        // 删除不再需要的空位
        List<Integer> toDelete = existingBlanks.stream()
                .filter(blank ->
                        dto.getBlanks().stream().noneMatch(b ->
                                Objects.equals(b.getBlankId(), blank.getBlankId()) ||
                                        Objects.equals(b.getBlankIndex(), blank.getBlankIndex())
                        )
                )
                .map(Blank::getBlankId)
                .collect(Collectors.toList());

        if (!toDelete.isEmpty()) {
            questionMapper.deleteBlanksByIds(toDelete);
        }
    }

    // 设置答案字段的私有方法（新增）
    private void setAnswerField(Question question, QuestionDTO dto) {
        if ("choice".equals(dto.getQuestionType())) {
            // 单选题：取第一个正确答案
            dto.getChoices().stream()
                    .filter(Choice::getIsCorrect)
                    .findFirst()
                    .ifPresent(c -> question.setAnswer(c.getChoiceContent()));
        } else if ("fill_in".equals(dto.getQuestionType()) &&
                dto.getBlanks() != null &&
                !dto.getBlanks().isEmpty()) {
            // 填空题：取第一个空位的答案
            question.setAnswer(dto.getBlanks().get(0).getAnswer());
        }
    }
}